package com.kaifamiao.myspringmvc.servlet;

import com.kaifamiao.myspringmvc.anno.Controller;
import com.kaifamiao.myspringmvc.anno.RequestMapping;

import java.io.File;
import java.io.FilenameFilter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author lucien-ma
 * @date 2021/10/8
 * @apiNote
 */
public class DispatcherServlet {

    Map<String, String> handlerMapping = new HashMap<>();

    public Map<String, String> getHandlerMapping() {
        return handlerMapping;
    }

    public void init(String packagePath) {
        // 获取输入的包名的绝对路径
        String absolutePath = getAbsolutePath(packagePath);
        // 获取该路径下的 java 文件名
        String[] javaFiles = getJavaFiles(absolutePath);
        // 获取全限定类名,并获取类对象
        for (int i = 0; i < javaFiles.length; i++) {
            String className = javaFiles[i].replace(".java", "");
            // 获取类对象
            try {
                Class clazz = Class.forName(packagePath + "." + className);
                // 判断有没有 @Controller 注解
                Annotation annotation = clazz.getAnnotation(Controller.class);
                if (annotation != null) {
                    // 说明有 @Controller 注解
                    // 进一步判断是否有 @RequestMapping 注解
                    // 首先获取所有方法
                    Method[] declaredMethods = clazz.getDeclaredMethods();
                    for (Method method : declaredMethods) {
                        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
                        if (requestMapping != null) {
                            // 说明有注解
                            // 有注解就说明，这个方法是用来处理请求的，所以放入到 map 集合中
                            handlerMapping.put(requestMapping.value(), clazz.getName() + "." + method.getName());
                        } else {
                            //System.err.println(method.getName() + "没有 @RequestMapping 注解");
                        }
                    }
                } else {
                    //System.err.println(clazz.getName() + "没有 @Controller注解");
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }


    }

    /**
     * 获取该路径下的 java 文件
     * @param absolutePath
     * @return
     */
    private String[] getJavaFiles(String absolutePath) {
        File absoluteFile = new File(absolutePath);
        String[] javaFiles = absoluteFile.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".java");
            }
        });
        return javaFiles;
    }

    /**
     * 获取绝对路径
     * @param packagePath
     * @return
     */
    private String getAbsolutePath(String packagePath) {
        // 将 . 替换成对应操作系统的分隔符
        String absolutePath = packagePath.replace(".", File.separator);
        // src 前面不能加 斜杠，否则就变成了绝对路径
        File absoluteFile = new File("src/main/java", absolutePath);
        return absoluteFile.getAbsolutePath();
    }

    public static void main(String[] args) {
        String p = "com.kaifamiao.myspringmvc.controller";
        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        dispatcherServlet.init(p);
        Map<String, String> handlerMapping = dispatcherServlet.getHandlerMapping();
        Set<Map.Entry<String, String>> entries = handlerMapping.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey() + "==>" + entry.getValue());
        }
    }
}
